
import java.io.BufferedInputStream;
import java.io.BufferedOutputStream;
import java.io.BufferedReader;
import java.io.IOException;
import java.io.InputStream;
import java.io.InputStreamReader;
import java.io.OutputStream;
import java.io.OutputStreamWriter;
import java.net.InetSocketAddress;
import java.net.ServerSocket;
import java.net.Socket;
import java.net.UnknownHostException;
import java.nio.ByteBuffer;
import java.nio.channels.SelectionKey;
import java.nio.channels.SocketChannel;
import java.nio.charset.Charset;
import java.util.ArrayList;
import java.util.concurrent.ArrayBlockingQueue;
import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;
import java.util.concurrent.ThreadPoolExecutor;
import java.util.concurrent.TimeUnit;

import com.sun.org.apache.bcel.internal.generic.NEW;


public class ProxyServlet{

	/**
	 * 
	 */
	private static String encoding = "GBK";

	private static final long serialVersionUID = 2706343257330041717L;
	ThreadPoolExecutor threadPool = new ThreadPoolExecutor(20, 30, 3, TimeUnit. SECONDS ,
			new ArrayBlockingQueue<Runnable>(2), new ThreadPoolExecutor.DiscardOldestPolicy() );
	public static void main(String[] args) throws IOException, Exception{
		(new ProxyServlet()).run();
		String inStr =
				"GET / HTTP/1.1\r\n"+
						"Accept: text/html, application/xhtml+xml, */*\r\n"+
						"Accept-Language: zh-CN\r\n"+
						"User-Agent: Mozilla/5.0 (compatible; MSIE 9.0; Windows NT 6.1; Trident/5.0)\r\n"+
						"Accept-Encoding: gzip, deflate\r\n"+
//						"Host: localhost:7888\r\n"+
						"Connection: Keep-Alive\r\n"+
						//						"Connection: close\r\n"+
						"\r\n";
				String line2 = getMsg(new Socket("www.baidu.com", 80), inStr);
				System.out.println(line2);
	}
	private final int POOL_SIZE=10;//单个CPU线程池大小
	public synchronized void run(){
		ServerSocket ss = null;
		ExecutorService executorService=Executors.newFixedThreadPool(
				Runtime.getRuntime().availableProcessors()*POOL_SIZE);
		try {
			ss = new ServerSocket(7888);
			System.out.println("Start...");
		} catch (IOException e1) {
			// TODO Auto-generated catch block
			e1.printStackTrace();
		}
		while(true) {
			try {
				Socket client=null;//客户Socket
				int contentLength = 0;// 客户端发送的 HTTP 请求的主体的长度
				client=ss.accept();
				System.out.println(client.toString());
				Runnable run = new Run(client);
				threadPool.execute(run);
			}
			catch (Exception e) {
				System.err.println(e);
			}
		}
	}
	public static String getMsg(Socket s, String content) throws Exception, IOException{
		//59.108.115.101 : 7888
//		if (s.isClosed()) {
//			s = new Socket("59.108.115.101", 7888);
//		}
		System.out.println(s.toString());
		OutputStreamWriter osw = new OutputStreamWriter(s.getOutputStream());
		osw.write(content);
		osw.flush();
		//		osw.close();
		InputStream is = s.getInputStream();
		//			BufferedReader reader = new BufferedReader(is);
		BufferedInputStream bis = new BufferedInputStream(is);
		//			bis.read()
		InputStreamReader isr2 = new InputStreamReader(is);
		BufferedReader reader2 = new BufferedReader(isr2);
		StringBuffer sBuffer2 = new StringBuffer();
		String line2 = "";
		while (!("\r\n").equals(line2 = readLine(is, 0))){
			sBuffer2.append(line2+"\r\n");
			//			System.out.println(line2);
		}
		//		isr2
		//		is.close();
		reader2.close();
		//		s.close();
		return sBuffer2.append("\r\n").toString();
	}
	public class Run implements Runnable{
		private Socket s;
		private Socket client;
		private SocketChannel channel;
		private Charset charset = Charset.forName("utf8");// 创建GBK字符集
		public Run(Socket socket)
		{
			try {
				s = new Socket("www.baidu.com", 80);
				//								s = new Socket("59.108.115.101", 7888);
				InetSocketAddress socketAddress = new InetSocketAddress(
						"www.baidu.com", 80);
				//step1:打开连接
				channel = SocketChannel.open(socketAddress);
			} catch (UnknownHostException e) {
				// TODO Auto-generated catch block
				e.printStackTrace();
			} catch (IOException e) {
				// TODO Auto-generated catch block
				e.printStackTrace();
			}
			this.client = socket;
		}
		public String getMsg(String content) throws Exception, IOException{
			//59.108.115.101 : 7888
//			if (s.isClosed()) {
//				s = new Socket("59.108.115.101", 7888);
//			}
			System.out.println(s.toString());
			OutputStreamWriter osw = new OutputStreamWriter(s.getOutputStream());
			osw.write(content);
			osw.flush();
			//		osw.close();
			InputStream is = s.getInputStream();
			//			BufferedReader reader = new BufferedReader(is);
			BufferedInputStream bis = new BufferedInputStream(is);
			//			bis.read()
			InputStreamReader isr2 = new InputStreamReader(is);
			BufferedReader reader2 = new BufferedReader(isr2);
			StringBuffer sBuffer2 = new StringBuffer();
			String line2 = "";
			while (!("\r\n").equals(line2 = readLine(is, 0))){
				sBuffer2.append(line2+"\r\n");
				//			System.out.println(line2);
			}
			//		isr2
			//		is.close();
			reader2.close();
			//		s.close();
			return sBuffer2.append("\r\n").toString();
		}
		public InputStream getMsg(InputStream content) throws Exception, IOException{
			//59.108.115.101 : 7888
			try {
				//				InetSocketAddress socketAddress = new InetSocketAddress(
				//						"www.baidu.com", 80);
				//				//step1:打开连接
				//				channel = SocketChannel.open(socketAddress);
				//step2:发送请求，使用GBK编码
				//				channel.write(null);
				//				channel.write(charset.encode("GET " + "/ HTTP/1.1" + "\r\n\r\n"));
				//step3:读取数据
				ByteBuffer buffer = ByteBuffer.allocate(1024);// 创建1024字节的缓冲
				int count = channel.read(buffer);
				while (count != -1) {
					buffer.flip();// flip方法在读缓冲区字节操作之前调用。
					System.out.println(charset.decode(buffer));
					// 使用Charset.decode方法将字节转换为字符串
					buffer.clear();// 清空缓冲
					count = channel.read(buffer);
				}
			} catch (IOException e) {
				System.err.println(e.toString());
			} finally {
				if (channel != null) {
					try {
						channel.close();
					} catch (IOException e) {
					}
				}
			}
			return s.getInputStream();
		}
		@Override
		public void run() {
			//			InputStreamReader isr;
			try {
				//				isr = new InputStreamReader(client.getInputStream());
				BufferedInputStream bis = new BufferedInputStream(client.getInputStream());
				BufferedOutputStream os = new BufferedOutputStream(s.getOutputStream());
				OutputStreamWriter osw = new OutputStreamWriter(os);
				byte[] buffer = new byte[1024];
//				int i = bis.read(buffer);
				BufferedReader bReader = new BufferedReader(new InputStreamReader(bis));
				String str = bReader.readLine();
				while (str != null) {
					//										bos.write(buffer);
					//										bos.flush();
					if (str.isEmpty()) {
//						str = bReader.readLine();
						break;
					}
//					os.write(buffer, 0, i);./
					if (!str.startsWith("Host:")) {
						osw.write(str+"\r\n");
					}
//					osw.flush();
					str = bReader.readLine();
//					System.out.println(new String(buffer, 0, i).charAt(250));
//					if( i < 1024) {
//						break;
//					}
//					i = bis.read(buffer);
					break;
				}
//				SocketChannel channel = s.getChannel();
//				s.
//				ByteBuffer bbuffer = ByteBuffer.allocate(1024);// 创建1024字节的缓冲
//				int count = channel.read(bbuffer);
//				while (count != -1) {
//					bbuffer.flip();// flip方法在读缓冲区字节操作之前调用。
//					System.out.println(bbuffer.toString());
//					// 使用Charset.decode方法将字节转换为字符串
//					bbuffer.clear();// 清空缓冲
//					count = channel.read(bbuffer);
//				}
				osw.write("\r\n");
				osw.flush();
////				os.close();
//				InputStream is = s.getInputStream();
//				OutputStream bos = client.getOutputStream();
				BufferedInputStream is = new BufferedInputStream(s.getInputStream());
				BufferedOutputStream bos = new BufferedOutputStream(client.getOutputStream());
				int i;
				while ((i = is.read(buffer)) != -1) {
					//										bos.write(buffer);
					//										bos.flush();
					if (i == 0) {
						continue;
					}
					bos.write(buffer);
					bos.flush();
					System.out.println(String.valueOf(buffer.toString()));
					if( i < 1024) {
						break;
					}
				}
				s.close();
				client.close();
			} catch (IOException e) {
				// TODO Auto-generated catch block
				e.printStackTrace();
			} catch (Exception e) {
				// TODO Auto-generated catch block
				e.printStackTrace();
			}
		}
	}
	/*
	 * 这里我们自己模拟读取一行，因为如果使用API中的BufferedReader时，它是读取到一个回车换行后
	 * 才返回，否则如果没有读取，则一直阻塞，直接服务器超时自动关闭为止，如果此时还使用BufferedReader
	 * 来读时，因为读到最后一行时，最后一行后不会有回车换行符，所以就会等待。如果使用服务器发送回来的
	 * 消息头里的Content-Length来截取消息体，这样就不会阻塞
	 * 
	 * contentLe 参数 如果为0时，表示读头，读时我们还是一行一行的返回；如果不为0，表示读消息体，
	 * 时我们根据消息体的长度来读完消息体后，客户端自动关闭流，这样不用先到服务器超时来关闭。
	 */
	private static String readLine(InputStream is, int contentLe) throws IOException {
		ArrayList lineByteList = new ArrayList();
		byte readByte;
		int total = 0;
		if (contentLe != 0) {
			do {
				readByte = (byte) is.read();
				lineByteList.add(Byte.valueOf(readByte));
				total++;
			} while (total < contentLe);//消息体读还未读完
		} else {
			do {
				readByte = (byte) is.read();
				lineByteList.add(Byte.valueOf(readByte));
			} while (readByte != 10);
		}

		byte[] tmpByteArr = new byte[lineByteList.size()];
		for (int i = 0; i < lineByteList.size(); i++) {
			tmpByteArr[i] = ((Byte) lineByteList.get(i)).byteValue();
		}
		lineByteList.clear();

		return new String(tmpByteArr, encoding);
	}
}
